﻿using Consul;

namespace RedDragon.RBAC.API
{
    public static class ConsulServiceCollectionExtensions
    {
        public static IServiceCollection ConsulRegister(this IServiceCollection services, Action<ConsulConfig> configAction)
        {
            var conf = new ConsulConfig();
            configAction(conf);
            services.AddSingleton(conf);
            return services;
        }

        public static IApplicationBuilder UseConsul(this IApplicationBuilder app, IServiceProvider serviceProvider, IHostApplicationLifetime lifetime)
        {
            ConsulConfig config = serviceProvider.GetService<ConsulConfig>();
            ConsulClient consulClient = new ConsulClient(
                            (c) =>
                            {
                                c.Address = new Uri(config.Address); //Consul服务中心地址
                                c.Datacenter = config.DataCenter; //指定数据中心，如果未提供，则默认为代理的数据中心。
                            }
                  );
            var ServiceName = config.ServiceName;
            //本地测试用localhost即可 保证心跳的接口可以正常访问
            var ServiceIP = config.localhost; //DNSHelper.GetLocalIP4();
            var ServicePort = config.ServicePort;

            var ServiceId = $"{ServiceName}_{ServiceIP}:{ServicePort}";
            var httpCheck = new AgentServiceCheck()
            {
                DeregisterCriticalServiceAfter = TimeSpan.FromMilliseconds(10), //服务停止后多久注销
                Interval = TimeSpan.FromSeconds(5), //服务健康检查间隔
                Timeout = TimeSpan.FromSeconds(5), //检查超时的时间
                HTTP = $"{Uri.UriSchemeHttp}://{ServiceIP}:{ServicePort}/HealthCheck" //检查的地址
                                                                                      //HTTP = $"{Uri.UriSchemeHttps}://{ServiceIP}:{ServicePort}/HealthCheck" //检查的地址
            };
            var registration = new AgentServiceRegistration()
            {
                ID = ServiceId, //服务编号，不可重复
                Name = ServiceName, //服务名称
                Port = ServicePort, //本程序的端口号
                Address = ServiceIP,//本程序的IP地址
                Checks = new[] { httpCheck },
            };

            consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册，内部实现其实就是使用 Consul API 进行注册（HttpClient发起）
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(registration.ID).GetAwaiter().GetResult();//服务停止时取消注册
            });

            //健康检测
            app.Map(config.HealthCheck, s =>
            {
                s.Run(async context =>
                {
                    await context.Response.WriteAsync("ok");
                });
            });
            return app;
        }
    }
}
